package chaoyue.study.controller;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * 尝试验证Redisson提供的各种锁功能
 * Redisson
 */
@RequestMapping("lock")
@RestController
public class LockController {
    @Autowired
    private RedissonClient redissonClient;
    // 锁key
    private static final String LOCK_KEY = "LOCK:chaoyue";

    /**
     * 加锁时不设置有效期，锁会自动续期，默认加锁30秒，每10秒续期一次
     * 观察Redis库中对应数据的过期时间
     * 可以看到每过10秒会自动给这个锁续期。直到unlock删除锁为止
     */
    @GetMapping("noTTL")
    public String noTTL() throws Exception {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        lock.lock();
        System.out.println("get lock prepare to sleep...");
        TimeUnit.SECONDS.sleep(60);
        System.out.println("wake up!!!");
        lock.unlock();
        return "test1 success";
    }

    /**
     * 加锁时设置有效期，锁不会自动续期
     * 观察Redis库中对应数据的过期时间
     */
    @GetMapping("withTTL")
    public String withTTL() throws Exception {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        lock.lock(30, TimeUnit.SECONDS);
        System.out.println("get lock prepare to sleep...");
        TimeUnit.SECONDS.sleep(60);
        System.out.println("wake up!!!");
        lock.unlock();
        return "test2 success";
    }

    /**
     * 尝试获取锁，如果没有获取到立即返回失败 不阻塞等待
     */
    @GetMapping("tryLock1")
    public String tryLock1() {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        boolean lockSuccess = lock.tryLock();
        if (lockSuccess) {
            lock.unlock();
            return "tryLock1 获取锁成功";
        } else {
            return "tryLock1 获取锁失败";
        }
    }

    /**
     * 尝试获取锁，如果没有没有获取到则在给定到时间CAS获取
     * 超过给定到时间还没获取到返回false
     */
    @GetMapping("tryLock2")
    public String test4() throws Exception {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        boolean lockSuccess = lock.tryLock(10, TimeUnit.SECONDS);
        if (lockSuccess) {
            lock.unlock();
            return "tryLock2 获取锁成功";
        } else {
            return "tryLock2 获取锁失败";
        }
    }

    @GetMapping("other")
    public String other() {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        lock.lock();
        System.out.println("other process...");
        lock.unlock();
        return "other success";
    }
}
